#!/usr/bin/env python

#socket.shutdown(how)
#how is SHUT_RDWR
#can be only _RD for read only (receives only), or WR for write only (sends only).

import time
import thread
import socket
import struct
import Map

#------------Networking stuff------------------

#test_world = "g g g g d d g g g g\n \
#	       g g g g d d g g g g\n \
#	       g g g g d d g g g g"


class Player: # Object that describes a player.
	def __init__(self, sock):
		self.username = ""
		self.password = ""
		self.worldX = 0 # Position in world - tile indices
		self.worldY = 0
		self.socket = sock


server_port = 1200 #The port the server is bound to
socket_num = 0 #How many sockets are in the servers list...
logged_in = [] #Contains all the sockets that are logged in

srvsock = UserSocket(socket.AF_INET, socket.SOCK_STREAM) # Server socket
srvsock.setblocking(0)

running = True # Obvious enough :P

directions = { # Used for communication
	"\x00":"up",
	"\x01":"right",
	"\x02":"down",
	"\x03":"left"
}

class MugServer:
	#We initialize the server here
	def __init__(self):
		self.time = 0
		self.port = server_port;
		srvsock.setsockopt( socket.SOL_SOCKET, socket.SO_REUSEADDR, 1 )
		srvsock.bind( ('', server_port) )
		srvsock.listen( 5 )
		srvsock.setblocking(0)
		self.descriptors = [srvsock] #contains all the server's sockets
		self.descriptors[0].setblocking(0)
		logged_in = [srvsock]
		logged_in[0].setblocking(0)
		
		socket_num = 1 
		print('MUG Server started on port %s' % server_port)

	def tick(self):
		while self.time+1 < time.clock():
			time.sleep(0.05) # Make this value smaller for more precise and CPU-intensive timing or bigger for less precise but less CPU-intensive timing. The value will have no effect on the speed of the program itself because it only runs while the program is waiting for the next update time to come.
		self.time = time.clock()

	#Call this once every second.
	# XXX: Imprecise comment - this actually runs the main loop, doesn't just update.
	def update(self):
		while running == True:
			#(sread, swrite, sexc) = select.select(self.descriptors, [], [], 2) #The 4th paramater makes it wait 1 second for whatever. It limits the server to updating once per second, the way I want.
			
			for sock in self.descriptors:
				if sock == srvsock:
					self.accept_new_connection()
				if sock != srvsock:
					data_recieved = sock.recv(1024)
					print(repr(data_recieved)) # repr so that it prints hex readably
					state = "read"
					for byte in data_recieved:
						if state == "read":
							if byte == "\x01":
								state="command login"
							if byte == "\x02":
								state="command move"
							elif byte == "\x00":
								state="ping"
							continue
						elif state == "command login":
							if not byte == "\xFF":
								username += byte
							else:
								state = "get password"
							continue
						elif state == "get password":
							if not byte == "\xFF":
								password += byte
							else:
								state = "read"
						elif state == "command move":
							try:
								direction = directions[byte]
							except KeyError:
								print "Invalid direction for client %s, %s: Disconnecting client" % sock.getpeername()
								self.descriptors.remove(sock)
								break
							if direction == "up":
								sock.worldY += 1
							elif direction == "down":
								sock.worldY -= 1
							elif direction == "left":
								sock.worldX -= 1
							elif direction == "right":
								sock.worldX += 1
							state = "read"
							continue
			world_update() #Calls the function that updates the game world.
			self.tick() # Idle until we next need to update.


	def accept_new_connection(self):
		newsock, (remhost, remport) = srvsock.accept()
		newsock.setblocking(0)
		self.descriptors.append(newsock)
		newsock.send("You've connected to a prototype mug server.\r\n")
		newsock.send("Requesting login details\r\n")
		data_recieved = 'Client joined %s:%s\r\n' % (remhost, remport)
		print(data_recieved)

	def broadcast_string( self, string, omit_sock ):
		for sock in self.descriptors:
			if sock != srvsock and sock != omit_sock:
				sock.send(string)

		print(string)


#clisock, (remhost, remport) = srvsock.accept()

#def net_update():
#	str = clisock.recv(100)
#	clisock.send( str )
#	clisock.close()
#	print(str)


#---------------------------------------------

#------------Update the Game World Itself------------------

def world_update():
	print "updating world" #debugging output

	#TODO: Make this work
	for tile in map1.tiles: # for <temporary_name> in <list>, addict
		print "Tile's position: (%i, %i)" % (tile.wx, tile.wy)

#---------------------------------------------

#-----------Consider here on out to be the program entry point------

map1 = Map.Map(0) #Create a map.
map1.generate_test_map(10, 10) #Populate this new map with 10x10 tiles

Server = MugServer() #Create the server object.

Server.update() #Main program loop.

#On program exit, close the sockets.
clisock.close()
srvsock.close()
print "exited" #Debugging output.
